﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.EntityFrameworkCore;
using OnlineStore.Data;
using OnlineStore.Models;

namespace OnlineStore.Services.Support
{
    public class ProductService : IProductService
    {
        private readonly OnlineStoreDbContext _context;
        private readonly IHostingEnvironment _hostingEnvironment;

        public ProductService(OnlineStoreDbContext context,
            IHostingEnvironment hostingEnvironment)
        {
            _context = context;
            _hostingEnvironment = hostingEnvironment;
        }

        public Dictionary<string, IEnumerable<Product>> GetProductByType()
        {
            var result = _context.Products
                .AsEnumerable()
                .GroupBy(p => p.Type)
                .ToDictionary(g => g.Key, g => g.AsEnumerable());
            return result;
        }

        public async Task AddProductAsync(Product product, IEnumerable<IFormFile> images)
        {
            product.ShelfTime = DateTime.Now;
            var filePaths = await UploadImages(images);
            product.ImageUrl = filePaths.FirstOrDefault();
            product.ProductImages = filePaths.Select(path => new ProductImage {Url = path}).ToList();

            await _context.Products.AddAsync(product);
            _context.SaveChanges();
        }


        private Task<List<string>> UploadImages(IEnumerable<IFormFile> images)
        {
            var webRootPath = _hostingEnvironment.WebRootPath;
            var filePaths = new List<string>();
            foreach (var formFile in images)
            {
                if (formFile.Length <= 0) continue;

                var fileExt = formFile.FileName.Substring(formFile.FileName.LastIndexOf('.')); //文件扩展名
                var fileSize = formFile.Length; //获得文件大小，以字节为单位

                if (fileSize > 1024 * 1024 * 2) //2M
                {
                    //上传的文件不能大于2M
                    return null;
                }

                var newFileName = Guid.NewGuid().ToString("N") + fileExt; //随机生成新的文件名
                var filePath = $@"/Images/{newFileName}"; //上传文件的完整目录
                filePaths.Add(filePath);
                using var stream = new FileStream($@"{webRootPath}/{filePath}", FileMode.Create);
                formFile.CopyTo(stream);
                stream.Flush();
            }

            return Task.FromResult(filePaths);
        }

        public async Task UpdateProductAsync(Product product)
        {
            _context.Products.Update(product);
            await _context.SaveChangesAsync();
        }

        public async Task AddToCart(int productId, int userId)
        {
            var user = await _context.Users.Include(u => u.Cart)
                .ThenInclude(u => u.ProductInCarts)
                .FirstOrDefaultAsync(u => u.Id == userId);

            var exist = _context.ProductInCarts.FirstOrDefault(pc =>
                pc.ProductId == productId && pc.CartId == user.Cart.Id);

            // 商品不在购物车中
            if (exist == null)
            {
                user.Cart.ProductInCarts.Add(new ProductInCart
                {
                    CartId = user.Cart.Id,
                    ProductId = productId,
                    Quantity = 1
                });
            }
            else
            {
                exist.Quantity++;
            }

            await _context.SaveChangesAsync();
        }

        public async Task AddComment(int productId, int userId, ProductComment comment)
        {
            comment.UserId = userId;
            comment.ProductId = productId;
            comment.SubmitDate = DateTime.Now;
            await _context.ProductComments.AddAsync(comment);
            await _context.SaveChangesAsync();
        }

        public Product LoadProductWithDetails(int id)
        {
            var result = _context.Products
                .Include(product => product.ProductImages)
                .Include(product => product.Comments)
                .ThenInclude(comment => comment.User)
                .FirstOrDefault(product => product.Id == id);
            return result;
        }

        public IEnumerable<Product> GetAllProduct()
        {
            return _context.Products.ToList();
        }

        public async Task DeleteProduct(int id)
        {
            var product = await _context.Products
                .Include(p => p.ProductImages)
                .FirstAsync(p => p.Id == id);

            var webRootPath = _hostingEnvironment.WebRootPath;

            foreach (var filePath in product.ProductImages.Select(image => $"{webRootPath}/{image.Url}")
                .Where(File.Exists))
            {
                File.Delete(filePath);
            }

            _context.Remove(product);
            await _context.SaveChangesAsync();
        }

        public IEnumerable<Product> GetHotProduct(string type)
        {
            return _context.Products.Where(product => product.Type == type)
                .OrderByDescending(product => product.SalesVolume)
                .Select(product => product);
        }

        public Product FindProductById(int id)
        {
            return _context.Products.Find(id);
        }

        public Dictionary<string, IEnumerable<Product>> FindProductByName(string name)
        {
            var result = _context.Products.Where(p=>p.Name==name)
                .AsEnumerable()
                .GroupBy(p => p.Type)
                .ToDictionary(g => g.Key, g => g.AsEnumerable());
            return result;
        }

        public Dictionary<string, IEnumerable<Product>> FindProductByAuthor(string author)
        {
            var result = _context.Products.Where(p => p.Author == author)
                .AsEnumerable()
                .GroupBy(p => p.Type)
                .ToDictionary(g => g.Key, g => g.AsEnumerable());
            return result;
        }

        public Dictionary<string, IEnumerable<Product>> FindProductByPublisher(string publisher)
        {
            var result = _context.Products.Where(p => p.Publisher == publisher)
                .AsEnumerable()
                .GroupBy(p => p.Type)
                .ToDictionary(g => g.Key, g => g.AsEnumerable());
            return result;
        }

        public Dictionary<string, IEnumerable<Product>> FindProductByIsbn(string isbn)
        {
            var result = _context.Products.Where(p => p.Isbn == isbn)
                .AsEnumerable()
                .GroupBy(p => p.Type)
                .ToDictionary(g => g.Key, g => g.AsEnumerable());
            return result;
        }
    }
}